package com.qclix.inv;

import java.util.*;

import static java.util.Calendar.*;

/**
 * @author Pierre Moermans
 */
public abstract class CalendarHelper {
    /**
     * Returns the last (closest) Sunday preceding the date given in parameter
     * @param date
     * @return
     */
    public static Date getStartDayOfWeekBefore(Date date, int firstDayOfWeek) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(DAY_OF_MONTH, firstDayOfWeek - cal.get(DAY_OF_WEEK));
        return cal.getTime();
    }

    /**
     * Returns the first Saturday after the date given in parameter
     * @param date
     * @return
     */
    public static Date getFirstSaturdayAfter(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(DAY_OF_MONTH, SATURDAY - cal.get(DAY_OF_WEEK));
        return cal.getTime();
    }

    /**
     * Sets the time of the calendar to 23:59:59
     * @param cal
     */
    public static void setCalendarToEndOfDay(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
    }

    /**
     * Set the time of the calendar at 00:00:00
     * @param cal
     */
    public static void setCalendarToBeginningOfDay(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
    }

    /**
     * Returns a list containing all the dates between from and till
     * @param from the start date (included in the returned list)
     * @param till the end date (included in the returned list)
     * @return the list of dates
     */
    public static SortedSet<Date> getDates(Date from, Date till) {
        Calendar firstDayAfterDisplay = Calendar.getInstance();
        if (from.before(till)) {
            firstDayAfterDisplay.setTime(till);
        } else {
            firstDayAfterDisplay.setTime(from);
        }
        firstDayAfterDisplay.add(DAY_OF_MONTH, 1);

        Calendar theDay = Calendar.getInstance();

        if (from.before(till)) {
            theDay.setTime(from);
        } else {
            theDay.setTime(till);
        }

        SortedSet<Date> days = new TreeSet<Date>();

        while (theDay.before(firstDayAfterDisplay)) {
            days.add(theDay.getTime());
            theDay.add(DAY_OF_MONTH, 1);
        }

        return days;
    }

    /**
     * Calculates the first day of the month
     * @param month, from 0 to 11
     * @param year
     * @return the first day of the month, at time 00:00:00
     */
    public static Date getFirstDayOfMonth(int month, int year) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        CalendarHelper.setCalendarToBeginningOfDay(cal);
        return cal.getTime();
    }

    /**
     * Calculates the last day of the month
     * @param month, from 0 to 11
     * @param year
     * @return the last day of the month at time 23:59:59
     */
    public static Date getLastDayOfMonth(int month, int year) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(DAY_OF_MONTH));
        CalendarHelper.setCalendarToEndOfDay(cal);
        return cal.getTime();
    }
}
